/**
 * 系统信息采集模块
 * 收集CPU、内存、磁盘、网络等硬件信息
 */
const os = require('os');
const { execSync } = require('child_process');
const logger = require('./logger');

class SystemInfoCollector {
  constructor() {
    this.lastNetworkStats = null;
    this.lastCheckTime = Date.now();
  }

  /**
   * 获取CPU信息
   */
  getCPUInfo() {
    try {
      const cpus = os.cpus();
      const cpuModel = cpus[0]?.model || 'Unknown';
      const cpuCores = cpus.length;
      
      // 计算CPU使用率
      let totalIdle = 0;
      let totalTick = 0;
      
      cpus.forEach(cpu => {
        for (let type in cpu.times) {
          totalTick += cpu.times[type];
        }
        totalIdle += cpu.times.idle;
      });
      
      const idle = totalIdle / cpus.length;
      const total = totalTick / cpus.length;
      const usage = 100 - ~~(100 * idle / total);
      
      return {
        model: cpuModel,
        cores: cpuCores,
        usage: parseFloat(usage.toFixed(2))
      };
    } catch (error) {
      logger.error('获取CPU信息失败:', error);
      return {
        model: 'Unknown',
        cores: 0,
        usage: 0
      };
    }
  }

  /**
   * 获取内存信息
   */
  getMemoryInfo() {
    try {
      const totalMemory = os.totalmem();
      const freeMemory = os.freemem();
      const usedMemory = totalMemory - freeMemory;
      const memoryUsage = (usedMemory / totalMemory * 100).toFixed(2);
      
      return {
        total: totalMemory,
        free: freeMemory,
        used: usedMemory,
        usage: parseFloat(memoryUsage)
      };
    } catch (error) {
      logger.error('获取内存信息失败:', error);
      return {
        total: 0,
        free: 0,
        used: 0,
        usage: 0
      };
    }
  }

  /**
   * 获取磁盘信息
   */
  getDiskInfo() {
    try {
      const platform = os.platform();
      let diskInfo = [];
      
      if (platform === 'win32') {
        // Windows系统
        try {
          const output = execSync('wmic logicaldisk get size,freespace,caption', { encoding: 'utf8' });
          const lines = output.trim().split('\n').slice(1);
          
          lines.forEach(line => {
            const parts = line.trim().split(/\s+/);
            if (parts.length >= 3) {
              const drive = parts[0];
              const free = parseInt(parts[1]) || 0;
              const total = parseInt(parts[2]) || 0;
              const used = total - free;
              const usage = total > 0 ? ((used / total) * 100).toFixed(2) : 0;
              
              diskInfo.push({
                mount: drive,
                total,
                free,
                used,
                usage: parseFloat(usage)
              });
            }
          });
        } catch (error) {
          logger.warn('Windows磁盘信息获取失败:', error.message);
        }
      } else if (platform === 'darwin' || platform === 'linux') {
        // macOS 和 Linux
        try {
          const output = execSync('df -k', { encoding: 'utf8' });
          const lines = output.trim().split('\n').slice(1);
          
          lines.forEach(line => {
            const parts = line.trim().split(/\s+/);
            if (parts.length >= 6) {
              const mount = parts[parts.length - 1];
              // 跳过特殊挂载点
              if (mount.startsWith('/dev') || mount.startsWith('/sys') || mount.startsWith('/proc')) {
                return;
              }
              
              const total = parseInt(parts[1]) * 1024; // KB to bytes
              const used = parseInt(parts[2]) * 1024;
              const free = parseInt(parts[3]) * 1024;
              const usagePercent = parts[4].replace('%', '');
              
              diskInfo.push({
                mount,
                total,
                free,
                used,
                usage: parseFloat(usagePercent)
              });
            }
          });
        } catch (error) {
          logger.warn('Unix磁盘信息获取失败:', error.message);
        }
      }
      
      // 如果没有获取到磁盘信息，返回根目录信息
      if (diskInfo.length === 0) {
        diskInfo.push({
          mount: '/',
          total: 0,
          free: 0,
          used: 0,
          usage: 0
        });
      }
      
      return diskInfo;
    } catch (error) {
      logger.error('获取磁盘信息失败:', error);
      return [{
        mount: '/',
        total: 0,
        free: 0,
        used: 0,
        usage: 0
      }];
    }
  }

  /**
   * 获取网络接口信息
   */
  getNetworkInfo() {
    try {
      const interfaces = os.networkInterfaces();
      const networkInfo = {
        interfaces: [],
        macAddresses: []
      };
      
      for (const name in interfaces) {
        for (const iface of interfaces[name]) {
          // 跳过内部接口
          if (iface.internal) continue;
          
          networkInfo.interfaces.push({
            name,
            address: iface.address,
            mac: iface.mac,
            family: iface.family
          });
          
          // 收集MAC地址
          if (iface.mac && iface.mac !== '00:00:00:00:00:00') {
            if (!networkInfo.macAddresses.includes(iface.mac)) {
              networkInfo.macAddresses.push(iface.mac);
            }
          }
        }
      }
      
      return networkInfo;
    } catch (error) {
      logger.error('获取网络信息失败:', error);
      return {
        interfaces: [],
        macAddresses: []
      };
    }
  }

  /**
   * 获取网络流量统计
   */
  getNetworkStats() {
    try {
      const platform = os.platform();
      let rx = 0, tx = 0;
      
      if (platform === 'linux') {
        const output = execSync('cat /proc/net/dev', { encoding: 'utf8' });
        const lines = output.split('\n');
        
        lines.forEach(line => {
          if (line.includes(':')) {
            const parts = line.trim().split(/\s+/);
            if (parts.length >= 9) {
              rx += parseInt(parts[1]) || 0;
              tx += parseInt(parts[9]) || 0;
            }
          }
        });
      } else if (platform === 'darwin') {
        const output = execSync('netstat -ib', { encoding: 'utf8' });
        const lines = output.split('\n').slice(1);
        
        lines.forEach(line => {
          const parts = line.trim().split(/\s+/);
          if (parts.length >= 10) {
            rx += parseInt(parts[6]) || 0;
            tx += parseInt(parts[9]) || 0;
          }
        });
      }
      
      return { rx, tx };
    } catch (error) {
      logger.warn('获取网络流量失败:', error.message);
      return { rx: 0, tx: 0 };
    }
  }

  /**
   * 获取完整的系统信息
   */
  getSystemInfo() {
    try {
      const cpu = this.getCPUInfo();
      const memory = this.getMemoryInfo();
      const disk = this.getDiskInfo();
      const network = this.getNetworkInfo();
      const networkStats = this.getNetworkStats();
      
      return {
        // 基本信息
        hostname: os.hostname(),
        platform: os.platform(),
        osType: os.type(),
        osRelease: os.release(),
        arch: os.arch(),
        uptime: os.uptime(),
        
        // CPU信息
        cpu: {
          model: cpu.model,
          cores: cpu.cores,
          usage: cpu.usage
        },
        
        // 内存信息
        memory: {
          total: memory.total,
          free: memory.free,
          used: memory.used,
          usage: memory.usage
        },
        
        // 磁盘信息
        disk: disk,
        
        // 网络信息
        network: {
          interfaces: network.interfaces,
          macAddresses: network.macAddresses,
          rx: networkStats.rx,
          tx: networkStats.tx
        },
        
        // 时间戳
        timestamp: Date.now()
      };
    } catch (error) {
      logger.error('获取系统信息失败:', error);
      return null;
    }
  }

  /**
   * 格式化字节数
   */
  static formatBytes(bytes) {
    if (bytes === 0) return '0 B';
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
  }
}

module.exports = new SystemInfoCollector();
